home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-12-20 | 115.7 KB | 2,734 lines | [TEXT/MPS ] |
- @chapter Designing Games with Xconq
-
- In this chapter, you'll learn how to design new kinds of games with
- @i{Xconq}. @i{Xconq} has been designed to support the use of a variety
- of techniques to design, construct, and test your game idea.
- These techniques range from text file editing to online painting,
- and you will likely find a combination of techniques to be most
- effective.
-
- As the person customizing @i{Xconq},
- you will be called the @dfn{designer}.
- This term also indicates the primary activity, which will
- be to Design The Game. The capabilities described below are merely tools;
- it is up to you the designer to exercise discretion and
- judgement in using them.
- Some principles of game design will be discussed in at the
- end of this chapter.
-
- You design games using @i{Xconq}'s Game Design Language (GDL).
- GDL is @i{Xconq}'s common language for defining all parts of a game,
- from the entry in the menu that players select games from,
- down to the last tiny detail of a saved game.
- GDL resembles Lisp, although (at the present time) it is not a procedural
- language; there are no functions or even any control constructs.
- Instead, the contents of a file guide the creation or modification of
- @i{Xconq} objects representing types, tables, units, and so forth.
- While a game is being played, @i{Xconq} uses this data to decide
- what to do and what to allow players to do.
-
- (People often have trouble with parentheses in Lisp, but if you follow
- the same kinds of indentation rules that you always use in
- C or Pascal, then you will encounter no additional trouble.
- Also, many editors such as Emacs are intelligent enough to indicate
- when parentheses match, and automatically do proper indentation.)
-
- In this chapter, ``you'' always means means you the designer,
- and players will be referred to as ``players'' or ``users''.
- The distinction is important; as the game designer, you will encounter and
- deal with many technical issues, but if you master those issues,
- your players will see only a fun game to play.
-
- This chapter is merely an overview of game design machinery; for precise
- definitions, see Chapter 4.
- The glossary defines all the technical terms.
-
- A final caveat before plunging in: @i{Xconq} is an experiment in the design and
- construction of configurable games. This means I have had very little
- prior art on which to build, and there are lots of odd corners that
- have never been tested or even thought about. In this spirit, I would like
- to hear about weird cases, and ideas for how to handle them.
-
- @node A Tutorial Example,,,
-
- @section A Tutorial Example
-
- Before delving into the depths of the language,
- let's look at an example.
- Suppose you just finished watching a Godzilla movie,
- complete with roaring monsters, panic-stricken mobs,
- fire trucks putting out flames, and so forth,
- and were inspired to design a game around this theme.
-
- @subsection Basic Definitions
-
- Start by opening up a file, calling it something like @code{g-vs-t.g},
- or as appropriate for your machine, and then type this into it:
- @example
- (game-module "g-vs-t"
- (title "Godzilla vs Tokyo")
- (blurb "Godzilla stomps on Tokyo")
- )
- @end example
-
- This is a GDL @dfn{form}.
- It declares the name of the game to be @code{"g-vs-t"},
- gives it a name that prospective players can see in menus,
- plus a short description or @dfn{blurb}.
- The blurb should tell prospective players what the game is all
- about, perhaps whether it is simple or complex, or whether
- it is one-player or multi-player.
-
- The @code{game-module} form is optional but recommended;
- some interfaces use it to add the game to a list of games
- that players can choose from.
-
- The general syntax of @code{game-module} form is similar to that
- used by nearly all GDL forms;
- it amounts to a definition of an ``object'' (such as a game module or a
- unit type) with @dfn{properties} (such as name, description, speed, etc).
- Some properties are required, and appear at fixed positions,
- while others are optional and can be specified in any order,
- so they are introduced by name. The general format, then, looks like
- @example
- (<object> ... <required properties> ...
- ...
- (<property name> <property value>)
- ...
- )
- @end example
- There are very few exceptions to this general syntax rule.
-
- Now the first thing you'll need is a monster.
- In @i{Xconq}, each unit has a type, and you define the characteristics
- attached to the type.
- @example
- (unit-type monster)
- @end example
- This declares a new unit type named @code{monster},
- but says nothing else about it.
- Let's use this more interesting form instead:
- @example
- (unit-type monster
- (image-name "monster")
- (start-with 1)
- )
- @end example
- This shows the usual way of describing the monster.
- In this case, @code{image-name} is a predefined @dfn{property}
- that specifies the name of the icon that will be used to display
- a monster unit.
- The property @code{start-with} says that each side should start out
- with one monster. This isn't quite right, because there should only
- be one side with a monster, and this will give @i{each} side a monster
- to start out with, but we'll see how to fix that later on.
-
- We also need at least one type of terrain for the world:
-
- @example
- (terrain-type street (color "gray"))
- @end example
-
- Streets are to be gray when displayed in color, and get nothing if they
- are being displayed on a monochrome screen.
-
- These two forms are actually sufficient by themselves to start up a game.
- (Go ahead and try it.)
- However, you'll notice that the game is not very interesting.
- Although each player gets a monster, and an area consisting of all-street
- terrain is displayed,
- nobody can actually @emph{do} anything,
- since the defaults basically turn off all possible actions.
-
- @subsection Movement
-
- Well, that was dull.
- Let's give the monsters the ability to move by putting this form into
- the file:
- @example
- (add monster acp-per-turn 4)
- @end example
- The @code{add} form is very useful; it says to modify the existing
- type named @code{monster}, setting the property @code{acp-per-turn}
- to 4, overwriting whatever value might have been there previously.
- The @code{acp-per-turn} property gives the monster the ability to act,
- up to 4 actions in each turn.
- By default, the ability to act is 1-1 with the speed of the unit,
- so the monster can also move into a new cell 4 times each turn.
- If you run the game now, you will find that your monster can now get
- around just fine.
- Why 4?
- Actually, at this point the exact value doesn't matter,
- since nothing else is happening. If the speed is 1, then the turns
- go faster; if the speed is 10, then they go slower and more action
- happens in a single turn.
- In a complete design however, the exact speed of each unit can be
- a critical design parameter, and for this game, I figured that a speed
- of 4 allowed a monster to cover several cells in a hurry while not
- being able to get too far.
- Also, I'm planning to make panic-stricken mobs have a speed of 1,
- which is the slowest possible.
- Making actions 1-1 with speed is usually the right thing to do,
- since then a player will get to move 4 times each turn
- (later on we will see reasons for other combinations of values).
-
- The @code{add} form works on most types of objects. It has the
- general form
- @example
- (add <type(s)/object(s)> <property name> <value(s)>)
- @end example
- The type or object may be a list, in which the value is either given
- to all members of the list, or if it is a list itself, then the list
- of values is matched up with the list of types.
-
- @subsection Buildings and Rubble Piles
-
- To give the monster something to do besides walk around, add buildings:
- @example
- (unit-type building (image-name "city20"))
-
- (table independent-density (building street 500))
- @end example
- The @code{building} type uses an icon that is normally used for a
- 20th-century city, but it has the right look.
- The @code{independent-density} table says how many buildings will appear
- in the world. The definition of a table consists of three-part lists;
- the two indexes into the table, and a value. In this case, one index
- is a unit type @code{building}, the other is a terrain type @code{street},
- and the value is @code{500}, which means that we will get about 500
- buildings placed on a 100x100 world (look up the definition of this table
- in the index).
- You need some for testing purposes, otherwise you won't see any when you
- start up the game.
- In general,
- @i{Xconq} policy is not to do anything unless you've turned it on first,
- and then to give you ``reasonable'' defaults once things are turned on.
-
- We're going to let buildings default to not being able to do anything,
- since that seems like a reasonable behavior for buildings
- (although Baba Yaga's hut might be fun...).
-
- By default, buildings act strictly as obstacles; monsters cannot touch
- them, push them out of the way, or walk over them.
- In real(?) life of course, monsters squash buildings,
- so we have to define a sort of combat.
- @example
- (table hit-chance
- (monster building 90)
- (building monster 10)
- )
-
- (table damage
- (monster building 1)
- (building monster 3)
- )
-
- (add (monster building) hp-max (100 3))
- @end example
- Note that the @code{add} form allows lists in addition to single
- types and values, in which case it just matches up the two lists.
- The @code{add} tries to be smart about this sort of thing; see its
- official definition for all the possibilities.
- The sum total of these defns basically say that a monster has a 90%
- chance of hitting a building and causing 1 hp of damage;
- three such hits destroy the building.
- A monster's knuckle might occasionally be skinned doing this;
- a 10% chance of 3/100 hp damage is not usually dangerous,
- and feels a little more realistic without complicating things
- for the player.
-
- Now you can start up a game, and have your monster go over and
- bash on buildings. Simulated wanton destruction!
-
- By default, a destroyed building vanishes, leaving only empty
- terrain behind. If you want to leave an obstacle, define a new
- unit type and let the destroyed building turn into it:
- @example
- (unit-type rubble-pile (image-name "???"))
-
- (add building wrecked-type rubble-pile)
- @end example
- In practice, you have to be careful to define the behavior of rubble
- piles. What happens when a monster hits a rubble pile? Can the rubble
- pile be cleared away? Does it affect movement?
- Try these things in a game now and see what happens;
- sometimes the behavior will be sensible, and sometimes not.
-
- For instance, you will observe that the default behavior is for
- the rubble pile to be an impenetrable obstacle! The monster can't
- hit it, and can't stand on it, and in fact can't do anything at all.
- OK, let's fix it. Monsters are agile enough to climb over all sorts
- of things, so the right thing is to let the monster co-occupy the
- cell that the rubble pile is in. The default is to only allow one
- unit in a cell, but this can be changed:
- @example
- (table unit-size-in-terrain (rubble-pile t* 0))
- @end example
- This says that while all other units have a size of 1, rubble piles
- only have a size of 0. By default, each terrain type has a capacity
- of 1, so this allows one unit and any number of rubble piles to stack
- together in a cell.
-
- If you try this out, you'll find that the monster can now cross over
- rubble piles, but still has to bash buildings in order to get them
- out of the way.
-
- Incidentally, it can cause problems to set a unit size to zero,
- because it allows infinite stacking. Since buildings and rubble
- piles don't move, we can never get gigantic stacks of units, but
- @i{Xconq} will happily let hundreds of units share the same cell,
- which causes no end of headaches for players confronted with overloaded
- displays. A game is more playable if it has at least some limits
- on stacking. For instance, this limits stacking of rubble piles,
- and also keeps the monster out of really full-up places:
- @example
- (table unit-size-in-terrain (u* t* 1))
-
- (add t* unit-capacity 16)
- @end example
-
- @subsection Human Units
-
- Now you've got an ``interactive experience'' but no game;
- there's no challenge or goal.
- You could maybe make a two-or-more-player game where the players
- race to see who can flatten the mostest the fastest,
- but that's still not too interesting to anyone past the age of 5.
- Instead, we need to make some units for the people bravely
- (or not so bravely) resisting the monster's depredations:
- @example
- (unit-type mob (name "panic-stricken mob") (image-name "mob"))
- (unit-type |fire truck| (image-name "firetruck"))
- (unit-type |national guard| (image-name "soldiers"))
- @end example
- Note that a type's name may have an embedded space, but then you have to
- put vertical bars around the whole symbol (a la Common Lisp).
- Things are starting to get complicated,
- so let's define some shorter synonyms:
- @example
- (define f |fire truck|)
- (define g |national guard|)
-
- (define humans (mob f g))
- @end example
- You can use the newly defined symbols @code{f} and @code{g}
- anywhere in place of the original type names.
- The symbol @code{humans} is a list of types, and will be useful
- in filling several propertys at once.
-
- As with monsters, all these new units should be able to move:
- @example
- (add humans acp-per-turn (1 6 2))
- @end example
- The speeds here are adjusted so that monsters can chase and run down
- (and presumably trample to smithereens) mobs and guards,
- but fire trucks will be able to race away.
-
- Also note the use of a three-element list that matches up with the
- three elements in the @code{humans} list. This is a very useful
- features of GDL, and used heavily. It can also be a problem,
- since if you add or remove elements from the list @code{humans},
- every list that it is supposed to match up with also has to change.
- Fortunately, @i{Xconq} will tell you if any lists do not match up
- because they are of different lengths.
-
- We still need to define some interaction, since monsters and humans
- can make faces at each other, and get in each other's way, but otherwise
- cannot interact.
- @example
- (add table hit-chance
- (monster humans 50)
- (humans monster (0 10 70))
- )
- @end example
- This time we have to say ``add table'' because we've already defined
- the @code{hit-chance} table and now just want to augment it.
-
- As with the addition of properties, we can use a list in place of
- a single type.
-
- Last but not least, we need a scorekeeper to say how winning and losing
- will happen. This is a simple(-minded?) game, so a standard type will
- be sufficient:
- @example
- (scorekeeper (do last-side-wins))
- @end example
- The @code{do} property of a scorekeeper may include some rather elaborate
- tests, but all we want to is to say that the last side left standing
- should be the winner, and the symbol @code{last-side-wins} does just that.
-
- There might be a bit of a problem with this in practice, since in order
- to win, the monster has to stomp on all the humans, including fire trucks.
- But fire trucks can always outrun the monster, and cannot attack it
- directly either, which leads to a stalemate.
- You can fix this by zeroing the point value of fire trucks:
- @example
- (add f point-value 0)
- @end example
- Now, when all the mobs and guards have been stomped, the monster wins
- automatically, no matter how many fire trucks are left.
-
- @subsection The Scenario
-
- As it now stands, your game design requires @i{Xconq}
- to generate all kinds of stuff randomly,
- such as the initial set of units, terrain, and so forth.
- However, we @emph{are} doing a monster movie, so random combinations
- of monsters and people and terrain don't usually make sense.
- Instead of trying to define a ``reasonable'' random setup,
- we should define a scenario, either by starting a random
- game, modifying, and saving it, or by text editing.
- Since online scenario creation is hard to describe in the manual,
- let's do it with GDL instead.
-
- To define a scenario, we generally need three things:
- sides, units, and terrain.
- Now the basic monster movie idea puts one monster up against
- a bunch of people acting together, so that suggests two sides:
-
- @example
- (side 1)
-
- (side 2 (name "Tokyo") (adjective "Japanese"))
- @end example
-
- The @code{1} and @code{2} identify the two sides uniquely,
- since we'll have to match units up with them in a moment.
- The side that plays the monster is really a convenience;
- players should just be aware of the one monster unit,
- so we don't need any sort of names.
- The other side has many units, which should be qualified
- as @code{"Japanese"}, and the side as a whole really represents
- the city of Tokyo, so use that for the side's name.
-
- Now for the units:
-
- @example
- (unit monster (s 1) (n "Godzilla"))
-
- (unit firetruck (s 2))
- (unit firetruck (s 2))
-
- (building 9 10 2)
-
- (define b building) ; abbreviate for compactness' sake
-
- (b 10 10 2)
- (b 11 10 2 (n "K-Mart"))
- (b 12 12 2 (n "Tokyo Hilton"))
- (b 13 12 2 (n "Hideyoshi's Rice Farm"))
- (b 14 12 2 (n "Apple Japan"))
- ;; ... need lots of buildings ...
- @end example
-
- This example shows two syntaxes for defining units:
- the first is introduced by the symbol @code{unit} and
- requires only a unit type (or an id, see the definition in xxx),
- while the second is introduced by
- the unit type name itself and requires a position and side.
- The second form is more compact and thus suitable for setting up large
- numbers of units, while the first form is more flexible, and can be used
- to modify an already-created unit. In both cases, the required data
- may be followed by optional properties in the usual way.
-
- Also, since the word ``building'' is a little longwinded,
- I defined the symbol ``b'' to evaluate to ``building''.
- GDL has very few predefined variables,
- so you can use almost anything, including weird stuff like
- ``&'' and ``=''.
- Property names like @code{s} and @code{n} are NOT predefined
- variables, so you can use those too if you like.
-
- At this point, you should have a basic game scenario,
- with one player being Godzilla, and the other trying to
- keep it from running amuck and flattening all of Tokyo.
- Have fun!
-
- You can enhance this scenario in all kinds of ways,
- depending on how ambitious you want to get.
- Given the basic silliness of the premise, though,
- it would be more worthwhile to enhance the silliness
- and speed up the pace, rather than to add features and details.
- For instance, name the buildings after all the laughingstock
- places you know of in your own town.
-
- To see where you could go with this, look at the library's @code{monster}
- game and its @code{tokyo} scenario, which include fires, different kinds
- of terrain, and other goodies.
-
- @section Types
-
- Types are the foundation of all @i{Xconq} game designs.
- Types are like classes in object-oriented programming but simpler;
- each set of types is fixed and used only in a particular way by @i{Xconq}.
- A game design defines types of units, materials, and terrain.
- Only materials are optional; every game design must define at
- least one unit type and one terrain type.
-
- Types in GDL are simple compared to most other languages.
- There is no inheritance, no subtyping, no coercions or conversions.
- This is not a real limitation, since game designs are usually too
- small to make effective use of any sort of inheritance.
- Also, game design is an exacting activity;
- inheritance is often difficult to control satisfactorily.
- You can use lists of types to simulate inheritance as necessary;
- this is actually more flexible, because you can have any
- number of lists with any set of types in each.
- It may not seem as efficient, but GDL is only used during
- startup, and is almost entirely array- and struct-based during
- the game. (A few places, such as scorekeeping, examine GDL forms
- during play.)
-
- Types are defined one at a time in the game module file.
- Each type gets an index from 0 on up, in order of the type's
- appearance in the file. Although this is not normally visible
- to you or to the player, some error messages and other places
- will make reference to raw type indices.
- Each category of type - unit, material, and terrain
- is indexed individually.
-
- @subsection Unit Types
-
- Unit types define what the players get to play with.
- Unit types can include almost anything; people, buildings, airplanes,
- monsters, arrows, boulders, you name it.
-
- The basic form of a unit type definition is so:
- @example
- (unit-type @var{type-name} (@var{property-name} @var{property-value}) @dots{})
- @end example
- The appearance of this form in a file means you are adding a new and
- distinct type, which has no relation to any other types defined before
- and after this one. The @var{type-name} must be a unique symbol,
- such as @code{building} or @code{|fire truck|}. (Note that you can set
- things up so that players never see the @var{type-name} anywhere,
- so don't worry if your preferred name conflicts with something else,
- just choose another name.)
- The @var{property-name} and @var{property-value} pairs are entirely optional.
- They can always be defined or changed later in the file.
- There is little advantage one way or another.
-
- This particular syntax - keyword followed by name or other identifier
- followed by property/value pairs - will be used for most GDL definitions.
-
- The number of unit types is limited. The exact limit depends on the
- implementation, but is guaranteed to be at least 127.
- This is a huge number of types
- in practice; the only situations where this might be needed would be
- a fantasy-type game with many types of items and monsters.
- For empire-building games, 8-16 unit types is far more reasonable.
- Keep in mind that with lots of types, players have more to keep track of,
- internal data structures will be larger and take longer to work with,
- and designing the game will take more time and energy.
- Consider also that @i{Xconq} gives you a lot of properties
- that you can set individually for each unit type,
- so that when other game systems might require a distinct types, @i{Xconq}
- lets you use the same type with different propertys.
- For instance, in a fantasy
- game you wouldn't need to define ``young dragons'' and ``old dragons'' as
- distinct types, instead you can vary the hit points or experience of
- a generic ``dragon'' type.
-
- @subsection Terrain Types
-
- Each cell in the world has a terrain type. This type should be thought
- of as the predominant contents of the cell, whether it be open ground,
- forest, city streets, or the vacuum of deep space.
- The type can be anything
- you want, and should be adapted to fit the game you're designing.
- Sure, the real world has swamps, but if you're designing a game set
- in the Sahara, don't bother defining a swamp terrain type.
- Also, the type doesn't carry any preconceptions about elevation
- or climate, so you can have swamps at 20,000 feet just as easily
- as at sea level.
-
- The limit on the number of terrain types is large
- (up to about 127, depending on the implementation),
- but in practice, 6-10 types offer variety without being confusing.
- Ideally, several of those types will be uncommon in the world,
- so that map displays will consist mostly of 3-4 types of terrain.
-
- Some game designs involve entities that are very large and do not move around.
- Such entities could plausibly be represented either as non-moving units or as a
- distinct terrain type. To make the right choice, you need to consider the
- special characteristics you want to implement. Terrain cannot (usually)
- be changed during the game, nor can it be moved, but units can be damaged
- or belong to different sides. A realistic example of this choice occurs
- in the monster game - should a destroyed building become a ``rubble-pile''
- unit or should the building stand on rubble-pile terrain and vanish when
- it is destroyed? Both choices are plausible; if the rubble-pile is a unit,
- then the original building is then on top of an empty city block, and after
- the building is destroyed, the rubble-pile unit can itself be cleaned off,
- exposing the empty city block again. However, you have to decide whether
- the rubble-pile unit belongs to a side, how it interacts with other units,
- and so forth. Rubble-pile terrain is simpler, but the players then get
- descriptions of brand-news buildings sitting in the midst of rubble-piles,
- which is confusing. This is a case where there is no ``right'' answer.
-
- @subsection Material Types
-
- Material types are the simplest to define. They have only a few properties
- of their own; most of the time they just index tables along with the
- other types.
- Materials do not act on their own in any way; instead, players
- manipulate materials as part of doing other actions.
- For instance, you can specify that movement, combat, and even a
- unit's very survival depends on having a supply of some material,
- or that some material is ammo and consumed gradually when fighting.
-
- The use of materials is pretty much up to you. You don't have to
- define any material types at all,
- and game designs with materials are usually more complicated.
- However, the increase in realism is often worth it;
- with materials you can limit player activity
- and/or make some actions more ``expensive'' than others.
-
- As with the other types, you can define up to about 127 material types,
- but that would be enough to model the entire global economy
- accurately! (and take all week to compute a single turn...)
- 1-3 types is reasonable.
-
- @subsection Hints
-
- It is tempting to try to define independent sets of types,
- each in a separate module, and glue them together somehow.
- However, this doesn't work well in practice, because in a game,
- the types interact in unexpected ways.
- Suppose, for example, that you define a set of airplane types that
- you want to be generic enough to use with several different games.
- The assessment of those types may vary drastically from game to game;
- in one, airplanes are 100 times faster than any other sort of unit,
- so that moving airplanes takes up 99% of game play, while in another,
- the same set of airplane types are too weak to be of any interest to
- players.
-
- There is a standard set of terrain types called @code{"stdterr"}.
- This set has a mix of the types found most useful for ``Empire-type'' games,
- and Earth-like percentages for random world generation.
-
- @section Setting up a Game
-
- You have a spectrum of options for how @i{Xconq} will set up a game
- based on your design. At the one end, you can build a scenario that
- specifies everything exactly, down to the last unit. Lest you think
- this is too restrictive to be interesting, consider that this is
- how chess works...
- At the other end of the spectrum,
- you can let @i{Xconq} manufacture everything,
- starting only with a handful of numbers that you supply.
-
- The next several sections describe the alternatives available for
- game setup. It is important to understand what is possible,
- because in general the character of an @i{Xconq} game will depend
- strongly on the initial setup, and players will be very angry
- (with you!) if they discover, several hours into a hard-fought game,
- that they've been given a grossly unfair starting position.
-
- @section Designing the World
-
- The @i{Xconq} world/area is a two-dimensional grid of fixed shape and size.
- You can make it represent part of a planet in space, by defining the
- circumference of the world,
- or just to make it be itself and not address the question
- of the surrounding context. The appropriate choice depends on how much
- realism and complexity you need. Most computer games don't bother with
- this detail; for instance, a game set in an underground dungeon doesn't
- usually need to compute daylight, weather, or seasons. However, these
- same details are very important for games set outdoors.
-
- @subsection World Shape and Size
-
- Once you've decided whether the area is to be part of a planet or not,
- you can address the question of size and shape.
- You have two choices for shape: hexagon and cylinder.
- (See the players chapter for pictures of these.)
- The important thing for you as a a designer is that the cylinder
- wraps around, while the hexagon is bounded on all sides.
- One consequence is that games involving pursuit will be quite
- different; on a cylinder, the chase can go round and round forever,
- while on a hexagon, a fleeing unit could be cornered.
- Cylinders have a disadvantage in that there is no obvious ``starting place''
- for coordinates, scrolling, etc, so there is a navigation and orientation
- problem for players, especially if the world is randomly generated and not
- the familiar continents of the Earth. In fact, players will often not
- even realize that a world is a cylinder and will assume that the edge
- of the display is the edge of the world! To make a cylindrical area,
- set the circumference of the world equal
- to the width of the area. Otherwise, the area will be handled as a hexagon.
-
- You can choose either to set a fixed size using the @code{area} form,
- or allow players to set the actual size via the @code{world-size} variant,
- in which case you can define the allowable range of sizes.
-
- Worlds need not be really large. Larger worlds are harder for
- players to manage, they take longer to display, and can consume
- prodigious amounts of memory (since they are represented as arrays
- internally, for speed). The ideal range of sizes depends primarily
- on the size and speed of units. A 60x60 area in a game with units whose
- speed is 1 means that they will take 60 turns to cross, while units with
- a speed of 20 take only 3 turns, so they make the world ``feel smaller''.
- As another example, in the standard game,
- a 20x20 area allows player to come to grips quickly, but it also
- means that each player's cities will be within bomber range right
- from the outset, which has a drastic effect on strategy.
- For exploration-oriented games, larger worlds are more interesting.
-
- @subsection World Terrain
-
- The best technique is for designing the terrain of a world is
- to use the designer tools provided with @i{Xconq}.
- The details of these tools depend on the interface, but in general
- they resemble the tools found in paint programs.
- Some interfaces also give you the option of rescaling the map,
- so that you can fine-tune the size and positioning of the terrain.
-
- Another technique is to write a program that translates data from another
- source (such as NASA satellite data) into @i{Xconq} format.
- If you do this and call it a hex world, then everything will appear
- to be tilting to the left.
- @c make into proper TeX eventually
- To fix this, map each cell (x, y) to (x - y / 2, y) before writing.
-
- The crudest technique is to try to build terrain by using a text editor.
- The coordinate system is Cartesian oblique, with the y axis tilted to form
- a 60-degree angle with the x axis, so it can be difficult to relate
- typed-in characters to the final appearance. Landforms in the file should
- appear to be leaning to the left, if they are to appear upright during play.
- However, sometimes text editing is necessary, for instance when you need
- to change every instance of a terrain type to something else.
- (Incidentally, some of
- the large real-world maps in the library
- were produced by coding all the terrain types from an atlas onto
- graph paper, typing them in, then fixing the tilt as described above.)
-
- Incidentally, areas should have some distinguishing terrain
- around the edges; this prevents player confusion that sometimes
- happens when there is no other clue as to where the edge might be.
- However, this is not enforced by @i{Xconq}, and you can put
- whatever you like along the edges.
- Randomly generated worlds normally use the value of
- the global variable @code{edge-terrain}.
-
- @subsection Synthesizing World Terrain
-
- The random way to get terrain for a world is to use one of several
- synthesis methods.
-
- Totally random terrain is available via the synthesis method
- @code{make-random-terrain}. This just randomly chooses a terrain
- type for each cell, using the weights in the @code{occurrence}
- property of each type. An @code{occurrence} of 0 means that the
- type will never be placed anywhere.
- This method produces a sort of speckly-looking world,
- and is better for testing than for actual play. Still, if you have
- two types @code{vacuum} and @code{solar-system}, then a form like
- @example
- (add (vacuum solar-system) occurrence (20 1))
- @end example
- will give you a nice starfield for a space game.
-
- The fractal world method @code{make-fractal-percentile-terrain}
- descends from the most venerable part of @i{Xconq}
- (it was once a piece of Atari Basic code). It uses a fractal algorithm
- along with percentile-based terrain classification to make realistic-looking
- worlds with terrain and elevations.
-
- To use this method, you first specify how many, what size, and what height
- of blobs to splash onto the world,
- and how many times to average cells with their
- neighbors. Then you specify the subdivision of all the possible altitudes
- and moisture levels into different kinds of terrain.
- For instance, desert in the standard terrain ranges from
- sea level (@code{alt-percentile-min} = 70%)
- to high elevations (@code{alt-percentile-max} = 93%) but only
- in the lowest percentiles of moisture (@code{wet-percentile-min} = 0%,
- @code{wet-percentile-max} = 20%).
- It is important that all percentiles be assigned
- to some terrain type, or the map generator will complain and subsitute
- terrain type 0 (the first-defined type); when designing
- terrain percentiles, it is helpful to make a chart with altitude percentiles
- 0-100 on one axis and moisture percentiles on the other.
- Note that overlapping on this chart is OK, and the terrain generator
- will pick the lowest-numbered terrain.
- Also note that you don't have to include every terrain type.
-
- The alt numbers are also used to compute elevations
- for games that need them, but the wet numbers need not have anything to do
- with water at all; they could just as easily represent smog levels or
- vegetation densities.
- If you only want to use one of the two layers, just set the percentiles
- for the other to be 0 - 100 for all terrain types.
-
- [should have an example]
-
- [is this correct still?]
- The method @code{make-maze-terrain} produces a maze consisting
- of a mix of ``solid'', ``passageway'', and ``room'' terrain.
- It uses the @code{maze-room-density} and @code{maze-passage-density}
- properties of each terrain type to decide
- how much of each to use for rooms and passages.
- The method first does random terrain generation, using the
- @code{occurrence} property to decide how much of each terrain
- to put down (remember that @code{occurrence} defaults to 1 for
- all terrain types).
- Then it carves out rooms, and passageways between them.
- The passages and rooms are guaranteed to be completely connected.
-
- The method @code{make-earth-like-terrain} attempts
- to model the natural processes and generate terrain as similar as possible
- to what is observed on Earth today.
-
- You should note that at least one method for synthesizing terrain must be
- available, unless you can guarantee that terrain will be loaded from a
- file. The following subsections describe optional additional synthesis
- methods that you can include.
-
- @subsection Rivers
-
- You can use the @code{make-rivers} method to add rivers to the world.
- Rivers are basically water features that depend on terrain elevations,
- so they won't be generated unless both a river terrain type (either
- border or connection) and elevation data is available.
- You get them by specifying a nonzero chance for some type of
- terrain to be the location of a headwater (@code{river-chance}).
-
- @i{Xconq} doesn't have any intuition about the behavior of water;
- it will happily trace rivers all the the way down to the bottom of the sea.
- Use the @code{liquid} property to tell @code{make-rivers}
- what types that rivers cannot touch.
- The method still traces the river's course, and resume modifying
- terrain when possible, which means that the river can appear
- as both the inlet and outlet from a lake.
-
- @subsection Roads
-
- The @code{make-roads} method is a fairly generic method.
- It just picks pairs of units randomly and runs a road between them,
- attempting to share road segments and route through favorable terrain.
- Although simplistic, the results look pretty good.
-
- You can make short bridges by tweaking the road density
- appropriately. Just allow roads from land to water, and water to land,
- but not from water to water.
-
- Note that this method is only useful after the units have been placed
- that the roads will connect.
-
- @section Designing the Sides
-
- Sides represent the players in a game. They also serve as a repository
- of information shared by units, such as technology and knowledge
- of the world.
-
- You should first decide how much about the sides will be predefined.
- If you're doing Eastern Front scenarios, it's very easy;
- you have Russians and Germans and that's it. If you're doing a
- science-fiction empire-building free-for-all, you may not have to
- specify anything more than a random side name generator.
-
- @subsection Predefined Sides
-
- For scenarios and similarly-restrictive games, the game design should create
- the sides directly, as in this example:
- @example
- (side (name "Germany") ... (colors "black,gray") ...)
-
- (side (name "Russia") ... (colors "red") ...)
- @end example
-
- Since the initialization machinery allows matching any player with
- any side, you can get away with being really vague.
- This will create four sides but not say anything about them:
- @example
- (side)
- (side)
- (side)
- (side)
- @end example
-
- If you're going to have predefined units on each side, then you should
- add an id to each side:
- @example
- (side 1 (name "Germany") ... (colors "black,gray") ...)
-
- (side 2 (name "Russia") ... (colors "red") ...)
- @end example
-
- @subsection Side Library
-
- If your game design does not predefine all the sides,
- you can define a @dfn{side library} using the @code{side-library} variable.
- Basically the library is a weighted list of collections of side properties,
- each formatted as a side definition.
- @i{Xconq} will use this library for any player that is allowed in the
- game but who does not have a side already, and select a side with
- a probability determined by the weights.
- Each item in the library will be used up to a limit that can be specified
- with each item;
- if the library has been exhausted before all the sides have been created,
- then the extra sides will just be assigned general defaults
- for their properties.
-
- The side library here makes futuristic sides for players,
- making two of the sides most likely, but allowing others as well:
- @example
- (set side-library '(
- (10 (name "Federation") (adjective "Federation") (class "fed"))
- (10 (name "Klingon Empire") (noun "Klingon") (class "klingon"))
- (5 (noun "Romulan") (class "romulan"))
- ((noun "Ferengi") (class "fed"))
- ((noun "Vulcan") (class "fed"))
- ))
- @end example
- Note that if the game design limits certain unit types to certain sides,
- the choice of sides will be more than just a cosmetic issue.
-
- @subsection Limits on Sides
-
- So that you can put upper and lower bounds on the number of sides in your
- game, GDL includes the variables @code{sides-min} and @code{sides-max}.
- As you might expect, every game design must allow at least one side.
- The upper limit on sides depends on the implementation, but is at least 7.
- Large numbers of sides can make a player's life very complicated,
- not to mention consuming vast quantities of memory, so you should
- try to limit the number of sides as much as possible.
-
- Another important limit is based on the notion of @dfn{side classes}.
- Each side can have a side class, and multiple sides can belong to the
- same class.
- For instance, sides named @code{"Hyperborean"} and @code{"Germanic"}
- could both have class @code{"barbarian"}.
- The value of side classes is that unit types have a property
- @code{possible-sides} that limits which side class(es)
- a type can belong to. This is very important for any game
- in which different players should have fundamentally different
- sorts of units. To continue the barbarians example, it is basically
- impossible for any barbarian side to have even one Roman legion,
- whether by construction, capture, or even surrender.
- So you can do something like
- @example
- (add legion possible-sides "roman")
-
- ...
-
- (side 1 (name "Rome") (class "roman"))
- (side 2 (name "Germania") (class "barbarian"))
- (side 3 (name "Hyperborea") (class "barbarian"))
- @end example
- and ensure that Roman legions are always Roman.
-
- @subsection Hints
-
- Note that a players tend to identify with the sides they're playing,
- so a game should allow for as much personalization as possible.
- On the other hand, some scenarios derive part of their flavor from
- predefinitions. For instance, a scenario with sides named
- ``German'' and ``Russian'', with appropriate colors and emblems,
- doesn't have quite the same feel when players rename them to ``Subgenii''
- and ``Simpsons''.
-
- A side can have a huge amount of state data, such as the current view.
- This rarely needs to be included in its entirety; synthesis methods
- will usually suffice to set view data correctly.
- Since total security is impossible with a predefined world,
- setting a side to have only a partial view won't necessarily
- be useful to keep players from knowing what that world really looks like.
-
- @section Designing the Units
-
- Once you've decided how to handle sides in your game,
- you can move on to the initial unit setup.
- Initial unit setup is very important, since it has a major
- bearing on how the rest of the game will go,
- and can be done in a number of different ways.
-
- @subsection Predefined Units
-
- GDL allows you to define everything about every starting unit in the game.
- This is a powerful approach, but requires much preparation.
- An advantage of predefined units is that there are no unpleasant surprises.
- For instance, suppose you designed a empire game with ships and cities,
- but a random setup leaves some players entirely landlocked.
- Not only will those players be @emph{very} unhappy, they might come
- looking for you @i{before} they've calmed down!
-
- Asking for initial units is pretty easy, you can either type them into
- a file or create them directly, using the appropriate designer tool in
- a game.
- @example
- (city)
- (city 11 12 1)
- (city (n "Brigadoon"))
- (city (@@ 10 10) (n "New York"))
- (city (@@ 20 10) (n "London") (hp 22))
- @end example
- The only info that you absolutely have to supply is the unit's type.
- If the position is missing, the unit will be placed at a random location.
- If the side number/name is missing, the unit will be independent or on the first
- possible side.
-
- While the type, position, and side of units is important, exact values of the
- other properties are rarely important for a scenario. Also, a unit with
- fewer filled-in properties can be used in different games.
- For instance, a list of the present-day major cities worldwide
- really needs only name and location for each;
- the game design can fill in everything else.
- One way to do this would be to set up an appropriate
- @code{unit-defaults} just before including the module.
-
- To make units start inside transports, you need to specify the @code{t#}
- property for the occupant, and have its value be the id number or name
- of some other unit. Your players may get an error message if the
- occupant is not of an allowed type for the transport to hold.
-
- @subsection Making Countries
-
- Despite the advantages of predefining initial units,
- this doesn't help when you want variable groups of units
- to appear in a randomly-generated world.
- Instead, you should use the @code{make-countries} synthesis method.
- The basic idea is that the method picks a good location for each side's
- country, scatters an initial set of units around that location,
- then possibly grows the country outwards.
- You can do anything from small widely-separated countries to an
- interlocking nightmare resembling pre-Bismarck Germany.
- Because of this, and because of the requirement that this
- method generate random setups that are as fair as possible,
- you have a great many parameters to work with.
- These parameters should be tuned carefully - you will probably
- need to generate and study lots of initial setups, especially
- if your parameters constrain the countries very tightly; the method
- cannot backtrack to fix a poor combination of placements.
-
- The first step in country generation is to select a location for
- each side's country. The location is a point that is the ``center''
- of the country (the exact value will be unimportant to players,
- and is not used outside this method). The constraints are that the
- center of each country is farther than @code{country-separation-min}
- from the center of every other country, that the center is within
- @code{country-separation-max} of at least one other country, and that the
- given initial area of the country (as defined by @code{country-radius-min})
- includes numbers of cells of each terrain type bounded by
- @code{country-terrain-min} and @code{country-terrain-max}.
-
- The reason for the separation constraints is that having countries
- too close together or too far apart can create serious problems.
- Consider the poor soul who gets tightly sandwiched between two enemies,
- thus becoming lunchmeat, ha ha, or the not-quite-so-poor-but-still-unlucky
- player who ends up on the wrong side of a very large world. (Keep in mind
- that your players may ask for a much larger world than you were thinking
- of when you designed the game.)
-
- The terrain constraints help you put the country in a reasonable mix of
- terrain. For instance, if you want to ensure that your countries include
- some land, but be on the coast rather than inland, then you should say that
- the country must have a minimum of 1 sea cell and 1 land cell. (In practice,
- the values should be higher, so you don't get small islands being used as
- entire countries and lakes being considered the ocean.) Keep in mind that
- these constraints may be impossible to satisfy, for instance if a particular
- world does not enough of the sort of terrain that is being required in a
- country. If the basic placement constraints fail, @i{Xconq} will just pick
- a random location, warn about it, and then leave it up to the players to decide
- whether to play the game ``as it lies''.
- @example
- ;;; Keep countries close together, but not too close.
-
- (set country-separation-min 20)
- (set country-separation-max 25)
- @end example
-
- Once @i{Xconq} has decided on locations for each country, it then places
- the initial stock of units. You define this initial stock via the
- unit properties @code{start-with} and @code{independent-near-start}.
- The @code{start-with} units start out belonging to the side, while the
- @code{independent-near-start} units are independent. The locations
- of these units are random within @code{country-radius-min} of the
- center, but are weighted according to the table @code{favored-terrain}.
- This table is very important; it is the percent chance that a unit of a given
- type will be placed in terrain of the given type. 100 is guaranteed to work,
- and 0 an absolute prohibition. Since @code{make-countries}
- tries repeatedly to place each @code{start-with} unit until it succeeds,
- then even terrain with a @code{favored-terrain} value of only 10% will get used
- if there is no other choice, so the table affects the distribution of units
- rather than the number that get placed. If a starting unit cannot
- be placed on any available terrain, but can be an occupant,
- then @i{Xconq} will attempt to put it inside
- some unit already present. This is a good way to begin a game with
- aircraft at airports rather than in the air.
-
- The upshot is that all this
- will do a reasonable layout if the parameters are set reasonably.
- If, however, @code{favored-terrain} is never > 0 for the @code{start-with}
- units and the country terrain,
- but there is some other terrain type for which this would work,
- @i{Xconq} will change the terrain.
- If even that doesn't work, the method will fail [or just complain?].
-
- This example is from the standard @i{Xconq} game:
- @example
- (set country-radius-min 3)
-
- (add city start-with 1)
- (add town independent-near-start 5)
-
- (table favored-terrain 0
- ((town city) plains 100)
- (town (desert forest mountains) (20 30 20))
- )
- @end example
- The net effect is to give each player one city outright and 5 towns nearby.
- Although created independent, these towns can be easily taken over right at the
- beginning of a game, so they are a kind of ``warmup'' (like the
- pushing of pawns at the beginning of a chess game). The @code{favored-terrain}
- table allows cities to appear only in plains, while giving more options to
- towns, since they can appear in deserts, forests, and mountains. Even so,
- towns are 5 times more likely to be in plains, which is reasonable.
-
- The optional last step in country generation is to grow the countries outwards
- from the initial area. This is basically a simple simulation of the
- historical forces that give countries their variety of shapes.
- The algorithm works by deciding whether to add to the country each cell
- at each distance from the country's center. The chance depends on the
- terrain type and whether the cell has
- already been given to another country. Once a cell has been given to the
- country, then the method decides whether to add a sided or independent unit
- to the cell, or whether to change the side of an existing unit.
- Country growth stops when either the absolute maximum radius has been
- reached, or too few cells have been added to the country, whichever comes
- first.
-
- This example is from one of the variants of the standard game:
-
- @example
- (game-module "standard"
- ...
- (variants
- ...
- ("Large Countries" eval
- (set country-radius-max 100)
- )
- ))
- @end example
-
- The resulting effect is to make all the countries border on each directly.
-
- @section Generating Names
-
- [put this with generic text generation?]
-
- One of @i{Xconq}'s special features is its extensive machinery
- for generating names of things.
- You can generate names for sides, units, and geographical features.
- The possibilities range from a simple list
- of strings up to context-free grammars and arbitrary code modules.
- Naming happens throughout the game, as nameable objects are created, but
- mostly happens during initialization.
-
- @subsection Grammar Examples
-
- Here is a very simple grammar:
- @example
- (namer (grammar root 40
- (root (or 1 (the animal in the thing)))
- (animal (or cat dog sheep))
- (thing (or hat umbrella fold))
- ))
- @end example
- It makes phrases like @code{"the cat in the hat"},
- @code{"the dog in the umbrella"}, and @code{"the sheep in the hat"}.
-
- This example is more realistic:
- @example
- ;;; German-like place name generator.
-
- ;;; Conventional combos most common, random syllables rare.
- ;;; Needs more conventional words to combine?
-
- (namer german-place-names (grammar root 50
- (root (or 95 (name)
- 5 ("Bad " name)
- ))
- (name (or 40 (prefix suffix)
- 20 (both suffix)
- 20 (prefix both)
- 5 (prefix both suffix)
- 10 (syll suffix)
- 10 (prefix syll suffix)
- ))
- (prefix (or
- schwarz blau grun gelb rot roth braun weiss
- wolf neu alt alten salz hoch uber nieder gross klein
- west ost nord sud
- ;; from real names
- frank dussel chem stras mut
- ))
- (suffix (or
- dorf torf heim holz hof burg stedt haus hausen
- bruck brueck bach tal thal furt
- ;; these aren't so great
- ach ingen nitz
- ))
- (both (or
- feld stadt stein see schwein schloss wasser eisen berg
- ))
- ;; Generate random syllables
- (syll (or 40 (startsyll vowel endsyll) 5 (vowel endsyll)))
- (startsyll (or 30 startcons 10 startdiph))
- (startcons (or b k d f g l m n r 5 s 3 t))
- (startdiph (or bl kl fl gl 5 sl 3 sch 2 schl
- br dr kr fr gr 2 schr 3 tr 2 th 2 thr))
- (vowel (or 6 a ae 2 au 5 e 2 ei 2 ie 6 i 3 o oe 2 u ue))
- (endsyll (or 4 b 5 l 3 n 4 r 4 t
- bs ls ns rs ts 3 ch 3 ck
- lb lck lch lk lz ln lt lth ltz
- rb rck rch rn rt rth rtz
- ss sz 2 th tz
- ))
- ))
- @end example
- This generator usually takes normal German words and glues a
- couple together, making names like @code{"Schwarzburg"},
- @code{"Nordbruck"}, and @code{"Bad Salzwasser"},
- but it will occasionally make a completely
- random syllable using common German phonemes, then glue it into a name,
- resulting in names like
- @code{"Biefeld"} and @code{"Salzgloelthach"}. Yes, that last one
- is unpronounceable even for Germans, but the generator doesn't
- know that!
-
- Since there is no special handling to ensure non-garbled names,
- it generally does not work particularly well to try to build
- names from vowels and consonants. Either random selection from
- a list or putting together syllables seems to do better, with
- perhaps a single totally random syllable thrown in. Don't forget
- that this is a generator, not a recognizer or parser,
- so you don't have to be able to handle
- every possible name; just enough to make an interesting variety.
-
- Recursive rules, where a symbol expands into a
- sequence mentioning that same symbol, will work, but they are not recommended.
- Although the generator has a builtin
- limiter to keep from looping forever,
- and the UGH list is available, [this is to be changed?]
- in general there is no way to avoid
- getting awful names like @code{"Feldbruckbruckbruck"}.
- Instead, you can just add extra rules, one for each desired length,
- so for instance you have a rule for 2-syllable names, one for 3-syllable
- names, one for 4 syllables, etc.
- Another advantage is that you can set the probability of each
- length of name separately,
- and thus lower the probability of longer names,
- so that they only appear once in a while
- and you save the poor players from being continuously tongue-tangled!
-
- @section Altitudes and Elevations
-
- [where should this section go?]
-
- @i{Xconq} is basically a 2-dimensional game,
- but you can emulate a third dimension by defining elevations for terrain
- and altitudes for units above and below the terrain.
-
- The main use of altitudes is to control interactions between certain kinds of
- units, particularly aircraft.
- For instance, a high-altitude bomber should be able to pass over a ship
- and under a satellite with impunity.
- In general, you define the ``operating altitudes" of a unit, so in the
- example above, you could say that a ship is always at the surface,
- bombers operate at 1-10 km, and satellites at 100-10,000 km.
- If a unit has more than one operating level, then it can move up and down
- by normal movement actions.
-
- Also, most details such as speed and material consumption are the
- same for a unit at any altitude. (Yes, such things vary in real life,
- but the effects are usually minor within the unit's normal operating
- range.)
-
- Altitudes also have a significant effect on combat.
- A unit at some altitude can only attack units at a specific range of altitudes
- up and down.
- Using the example again, you could define fighter aircraft to operate at
- 0-20km and be able to attack up and down 5km, while bombers can
- attack up to 10km down (i.e. down to the ground), but not up.
- Satellites remain invulnerable.
-
- All this applies equally to units underground and undersea.
-
- @section Tech
-
- Tech is useful when technological development is important
- to a game. There are several ways to use it.
-
- One use of tech is to track the results of research.
- You do this by setting the initial tech of a side to (say) 0,
- then requiring a certain tech (say 60) in order to build a desired type.
- If a research action adds 1 to a side's tech, then it will
- take 60 research actions to gain the necessary level.
- The number of turns will of course depending on how actions
- the researcher can do each turn, and how many researchers
- are available. So for instance, 10 researching units results
- in the work being done in 6 turns instead. You can limit this
- schedule acceleration by setting @code{tech-per-turn-max}.
-
- Another use of tech is to differentiate sides.
- Suppose you want to do a game involving earthlings and space aliens.
- The aliens can have satellites overhead that earthlings don't even
- know are there, they have equipment earthlings couldn't use even if
- they were able to capture it. However, earth scientists might learn
- something from it. To do all this, use @code{tech-to-see} and friends.
-
- Tech is fundamentally tied to unit types. However, many games have
- a number of unit types that share technology. For instance, advances
- in bomber technology usually lead to advances in fighter and surveillance
- aircraft. The @code{tech-crossover} table is available for this purpose.
-
- @section Static Relationships Between Types
-
- This section describes the ``static'' relationships between types of
- objects, meaning those relations which must always hold, both in the
- initial setup and throughout a game.
-
- @subsection Stacking
-
- By default, @i{Xconq} allows only one unit in each cell at a time.
- This has the advantage of simplicity, but also makes some bizarre
- situations, such as the ability of a merchant ship to prevent an
- airplane from passing overhead or a submarine from passing underneath.
-
- To fix this, you can allow players to stack several units in the
- same cell. This is governed by several tables, which give you control
- over which and how many of each type can stack together in which kinds
- of terrain. The basic idea is that a cell has a certain amount of room
- for units, as specified by the terrain type property @code{capacity},
- and each unit has a certain size in the cell, according to the table
- @code{unit-size-in-terrain}.
-
- @example
- (add (plains canyons) capacity (10 2))
-
- (table unit-size-in-terrain
- ((indians town) plains (1 5))
- ((indians town) canyons (1 2))
- )
- @end example
-
- In this example, a player can fit 10 indians or 2 towns into a plains cell,
- or else one town and 5 indians, while canyons allow only 2 indians or one town.
-
- In addition, some unit types may be able to count on a terrain type providing
- a guaranteed place; for this, you can use the unit/terrain table
- @code{terrain-capacity-x}. This table (which defaults to 0) allows
- the specified number of units of each type to be in each type of
- terrain, irrespective of who else is there. For instance,
- a space station could be given space via
- @example
- (table terrain-capacity-x (space-station t* 10000))
- @end example
- So while units on the ground are piling together and being constrained
- by capacity, space stations overhead can stack together freely (space
- is pretty big, after all).
-
- @subsection Occupants and Transports
-
- Occupants and transports work similarly to stacking in terrain;
- there is both a specialized capacity and a generic capacity that
- units' sizes count against.
-
- @example
- (add (transport carrier) capacity (8 4))
-
- (table unit-size-as-occupant
- ((infantry armor) transport (1 2))
- ((fighter bomber) carrier (1 4))
- )
-
- (table unit-capacity-x
- (carrier fighter 4)
- )
- @end example
-
- It may be that all the different sizes interact so that you can't
- prevent huge numbers of small units being able to occupy a single
- transport. To fix this, use @code{occupants-max}.
-
- Transport is a physical relationship, so for instance one cannot use
- transports to define a convoy whose acp-per-turn is determined by its
- slowest member. (This doesn't mean you can't define a convoy
- type, but you will have to pick an arbitrary speed for it.)
-
- @section Setup Miscellany
-
- @subsection Self-Units
-
- Normally a player runs the side as a whole,
- and all the units on that side are disposable and interchangeable.
- However, you require one unit to represent the player personally
- among the units of the player's side;
- this unit is the @dfn{self-unit}.
- What this means is that if that unit is captured or dies,
- the player loses the game instantly.
- All the other units on the side will behave normally as for losing,
- either going over to the side that captured the player,
- becoming independent, or disbanding.
-
- The idea is to increase the player's motivation for self-preservation.
- This is useful to introduce a risk of capture, assassination, and so forth.
- It also prevents bizarre and unrealistic strategies in some games.
-
- For instance, it sometimes happens in empire-building games that players
- end up switching countries, because each captured another's country and
- neglected to defend their own. If each player got one capital city,
- and that city were to be a self-unit, then the owner would have to defend
- it at all costs!
-
- To make this happen, you could do something like this:
- @example
- (set self-unit-required true)
-
- (add capital-city can-be-self true)
-
- (add capital-city start-with 1)
- @end example
-
- @section Units and Actions
-
- Players can do all kinds of things with their units. They can push
- the units around, they can make units build things, they can get into fights,
- or they can just let them sit around.
- You as the designer decide which kinds of things make sense in your
- game, then set up the action parameters appropriately.
- Is moving through swamps going to be slow?
- Can a small town build any kind of ship, or just small ones?
- How often can Godzilla breathe fire?
-
- Now, what the players work with is the interface, which can do all
- kinds of intelligent things -- whatever makes sense for that interface.
- However, no matter what the interface, no matter what kind of play
- automation, player input eventually breaks down into unit actions.
- The set of action types is predefined and can't be changed.
- They are also very primitive. Each action takes a number of arguments,
- such as the type of unit to build or the location to move to,
- the action just happens and either succeeds or fails on the spot.
- There are no actions that take longer than one turn to complete,
- and a unit can perform only one action at a time.
- This may seem horribly restrictive, but actions are just
- the low-level building blocks; players rarely see actions directly.
- You have to be aware of them because the game design specifies
- which unit types are capable of which actions.
- Each @i{Xconq} interface will adjust itself to disallow input that
- would result in types of actions that you have prohibited.
-
- The number of actions that a unit can do in one turn is limited
- by its action points. A unit with zero action points cannot do anything
- at all. A unit with lots of action points can do lots of actions,
- unless each action costs many action points.
- You can define the action point cost of each type of action for each
- unit type. In some cases, the cost will also depend on the action's arguments.
-
- Acp is actually a little like a bank account,
- since by not doing anything for awhile,
- a unit can accumulate extra acp (up to @code{acp-max}),
- and it can go into debt temporarily, down to @code{acp-min}
- (which may be a negative value).
- A unit in ``action debt'' at the beginning of a turn cannot move
- or do anything else, and must for a turn
- when its acp goes positive again. This can be a simple way to implement
- both fatigued units and units that can do more if they plan for it.
-
- Actions intrinsically both an actor and an ``actee''. The actor is
- the brains, and that is whose acp gets used up, but the actee has the
- action actually happen to it. This is so animate units (like humans)
- can work with inanimate units (like swords).
-
- @section Movement
-
- Movement is the most important action type. There are actually two distinct
- types of actions; one to enter a cell, and one to enter a unit.
-
- Each unit has a speed which is determined at the beginning of the turn
- and determines how many cells it can enter during the turn.
- However, terrain, borders, and other obstacles can consume extra
- movement points.
-
- @subsection Unit Speed
-
- Units have a base speed @code{speed} which is the ratio of mp to acp.
- You can set damaged units to move more slowly.
- You can also allow occupants to add to the speed, up to the
- @code{speed-max} limit.
-
- @subsection Movement Costs
-
- Typically the cell entry cost will be the most useful to adjust,
- although the departure cost can be useful in representing units
- mired in jungle mud
- and taking a long time to escape onto clear terrain.
-
- Be aware that complicated entry/exit costs are confusing to players,
- and AIs may not take them into account very well either.
- Using @code{free-mp} helps players use up all their acp.
-
- @subsection Entering Transports
-
- Different kinds of transports have different ways for units
- to get on and off. For instance,
- ships can dock, or use their boats to enable land units to get on and off.
- The tables @code{ferry-on-entry} and @code{ferry-on-departure}
- specify how much terrain units will have to cross on their own.
-
- [example]
-
- Observe that enter/leave costs can be used to make one-way trips.
- For instance, paratroops jumping out of a plane should be able
- to leave cheaply, but have an entry cost so high that they can
- only reboard in a later turn.
-
- @subsection Border Slides
-
- One of the problems with @i{Xconq} borders and connections is that
- neither works exactly like a sea strait. Consider the Straits of
- Gibraltar. They are so narrow that one can see the other side,
- but nevertheless impose a formidable barrier to landlubbers.
- At the same time, ships can pass through readily, if
- not secretly. If cells in the world are 60 miles across, then
- making an all-sea cell is a gross exaggeration.
- However, adding a water border only prevents both land and sea movement!
- To get around all this, @i{Xconq} allows a special kind of
- move called a ``border slide''.
- Basically, if both the destination cell and the border whose endpoints
- touch the start and end cells are allowable terrain for a unit,
- then the unit can move to the destination cell in one move.
- However, it incurs a special cost in addition to the normal entry
- and leave costs for the terrain in the two cells (but @i{not} the border
- crossing cost, since the border is not being crossed, exactly).
- This cost is in the table @code{mp-to-traverse}.
- Border sliding should usually be somewhat expensive, both because
- of the distance (the unit ends up two cells away after only one move),
- and because of the real-life difficulties of passing through a narrow
- strait. Note that border sliding does not escape the units on either
- side of the border, since the unit doing the sliding will still be
- adjacent to the cells on each side of the border it slid through.
-
- @subsection Leaving the Area
-
- This feature can be useful in allowing a non-disbandable unit type
- to escape capture or otherwise retire from action.
-
- @subsection Free Moves
-
- This is most useful in emulating some board games,
- or to prevent clever players from exploiting a mess of move costs.
- The default of @code{-1} is the most playable,
- since player will always be able to use all of their mp.
- Otherwise, there may be situations in which a unit has
- a few acp left, but not enough to go anywhere,
- and so they end up being wasted.
- The free move does not actually get subtracted from the unit's acp.
-
- @subsection Zone of Control
-
- Sometimes a unit can by its presence alone affect the movement of unfriendly
- units in the vicinity, perhaps by requiring them to hide or to move
- carefully in order to pass by, or even to prevent entry altogether.
- This is called the ``zone of control'' or ZOC.
-
- Exerting a ZOC requires no action, nor any particular capability on
- on the part of the unit exerting the ZOC. For instance, a toothless
- fort could still cause raiders to sneak by carefully (at least if they
- didn't know that it was toothless).
-
- @section Construction
-
- Construction is very important to empire-building and similar strategic
- games. The construction of a unit may involve as many as four different
- kinds of actions. This is so you can make construction be an expensive
- long-term process.
-
- The basic construction is unit creation. A player might have to do
- research and toolup actions in order to prepare for creation, and might
- also have to do completion actions, if the created unit is not ready to use.
-
- Normally the interface will just have a single "Build <type>" command,
- which then results in a task that issues appropriate actions, so players
- don't necessarily see all these different actions.
-
- @subsection Research
-
- Some types of units may be relatively easy to build, once you know how,
- but at the same time that type totally changes the balance of the game.
- The atomic bomb in WWII is the classic example; once it became available,
- everything changed.
-
- To allow research, set @code{acp-to-research} to 1 or more.
-
- [see Section xxx for more description of tech levels]
-
- @subsection Tooling Up
-
- Toolup costs are what you use to represent the overhead of changing
- construction. Quite often it does not need to be set. Its primary
- use is to encourage players to commit to grand strategy once chosen,
- because the cost of changing would be prohibitive.
-
- @subsection Creation
-
- Players can create a unit either inside another unit, or out in the open.
- The acp cost is that same in either case.
-
- @subsection Completion
-
- By default, newly-created units are complete and ready-to-use. This is
- rarely a good idea in a game design, since 1-acp unit can then create
- another unit on each turn. If you're going to allow that, then you
- should include something else keep players from being swamped by
- overpopulation. You can set high accident or attrition rates, make
- creation require scarce materials, only have one or a few of the creator
- type.
-
- The best way to slow down unit creation is to create incomplete
- units and then require build actions. Completeness is defined
- in terms of completeness points or cp that you can define for each
- type. A completion action just adds to completeness points.
- Incomplete units do in fact exist as units, so for instance they
- can be captured and completed by another side.
-
- You can set separation and build acp so that several units can
- cooperate to accelerate construction of a unit.
- There are no maximum rate limits set on this, but it's
- unlikely that players will ever be able to achieve much
- acceleration, because of the limit on the separation between
- the builder and the unit. For instance, the default separation
- of zero implies that multiple builders of a unit have to be in
- the same cell.
-
- @section Combat
-
- Not all games require fighting. Races and exploration
- can be lots of fun, and not need players to be bashing each other.
- However, the excitement of most @i{Xconq} games derives
- from the chances of going up directly against an opponent.
-
- Combat includes five distinct action types that a player may choose
- from, not counting detonation, and you specify the characteristics
- of each. ``Attack'' is hand-to-hand with another unit, ``capture''
- attempts to change the side without damaging, ``fire-at'' hits a unit
- without getting entangled, while ``fire-into'' hits everything
- in a targeted cell.
- Finally, ``overrun'' is an attempt to occupy a cell, doing whatever
- combination of attack, capture, and movement is necessary.
-
- To specify what kinds of battles are possible, you begin by setting
- the @code{hit-chance} of some unit vs another unit to any value
- greater than zero. A hit probability of zero completely disallows
- attack. A hit probability of 100 is a guaranteed hit.
- In practice, you will probably need to specify most hit probabilities
- individually.
-
- [describe mods to hit prob?]
-
- Next you need to set the damage done by a hit.
- The default value is 1 hp, which is a good starting place
- but not always particularly realistic.
-
- [describe variation parms]
-
- As usual, you can define the action point cost of combat.
- The attacker and defender use separate tables, which allows for
- some extra flexibility. This is important, because sometimes you
- want to allow combat to keep a defender busy and soak up its acp,
- while at other times attempts to engage in combat should be shrugged off.
- Consider battleships vs infantry; although combat between the two
- rarely causes much damage, an attack by a battleship will cause the
- infantry to keep their heads down, and preventing them from doing much else,
- while the return rifle fire is unlikely to keep the battleship
- from making its appointed rounds.)
-
- Describing simple hit probabilities and damage is oftentimes sufficient
- for a game. It's simple; players can learn the numbers by heart.
- It's more efficient, because there's no need to manage lots of
- ongoing battles. However, there are endless numbers of situations
- where this basic model is unsatisfactory, so let's move on to the
- available enhancements.
-
- The basic parameter for the firing actions is @code{range} of the unit,
- which is the greatest reach possible.
- You can also set a @code{range-min}, which is useful for ballistic
- missiles, certain kinds of artillery,
- and magic spells that can't used for close-in fighting;
- you can't fire at a unit that is less than @code{range-min} cells away.
-
- Also, you can define how transports and occupants affect each other in
- combat. The effects can be both positive and negative, and extend both
- from occupants to their transport and from the transport to its occupants.
- The table @code{transport-protection} defines the percentage of hit damage
- (by any unit type) that gets passed through to each occupant.
- If 0, then the transport is perfect protection. If 100, then each occupant
- gets the same hit as the transport did.
- [Ideally, protection is a prorating on table value from occupant vs attacking
- unit.]
- Note that an occupant cannot be attacked directly from outside its transport.
-
- If you want to make combat dependent on having a supply of ammo, use the
- tables @code{hits-with} and @code{hit-by}.
- The material type need not be explicitly designated as ammo,
- but both the hitting and hit units must agree that the same type
- is effectual (we assume that the attacking unit is smart enough not to
- use material types that have no effect on the target unit).
-
- [need a combat-supply usage in addition]
-
- @subsection Multi-Round Battles
-
- By default, combat actions are basically raids;
- one strike and it's all over.
- This of course is highly unrealistic, and leads players to
- engage in combat far more casually than is realistic.
-
- You make combat more involving by defining commitments to battles.
- Basically, units attack by raising their commitment from zero up to some
- values, and remain in combat until they die, are captured, or withdraw
- by reducing their commitment to zero again. At the start of each round,
- each unit that is participating has the choice of raising or lowering its
- commitment to the battle, within bounds that you define.
-
- Note that units in battle don't have to attack, but that they are
- prevented from doing other things. This can be useful not only
- for field battles, but sieges (cities have to deal with besiegers),
- and wrestling matches.
-
- @subsection Capture
-
- [say something about garrisoning rules]
-
- @subsection Detonation
-
- Detonation is an action type that represents a variety of explosive
- behaviors. It can be requested explicitly by the side, or happen
- automatically.
-
- A minefield could be implemented by defining a detonating unit that
- loses some small percentage of its hp every time a unit hits it,
- while hitting the other unit automatically.
-
- A simple trap would auto-detonate only once, then change to
- a ``sprung trap'' type.
- Then the right kind of unit could come along and do a change type
- action to reset it.
-
- @section Unit Manipulation
-
- The actions in this group are a mixed bag of manipulations.
- If they need to be in your game, then the need will be obvious,
- otherwise they are pretty much optional.
-
- @subsection Moving Unit Parts
-
- Any unit whose @code{parts-max} is greater than the default of 1
- is a multi-part unit, and its hp denotes size rather than amount
- of damage. Armies and fleets are two kinds of units which can
- be usefully defined as multi-part.
-
- Players will very often want to merge or detach parts of a multi-part
- unit, and there is an action provided for that.
- You can control the cost of the action by setting @code{acp-to-move-part}.
-
- @subsection Changing Side
-
- @subsection Changing Type
-
- @subsection Disbanding
-
- Sometimes a player will want to get rid of a unit,
- perhaps because some type has been overproduced and is tying up
- valuable resources, or to prevent it from falling into enemy hands.
-
- You can control this via @code{acp-to-disband}.
-
- It should usually not be possible to disband something large like a city,
- otherwise a clever player might try to eliminate it as a strategic target,
- but most mobile units should be easily disbanded.
-
- @section Material Manipulation
-
- You can allow players to produce materials by explicit action,
- and you can control how they transfer materials between units.
-
- Note that you can usually have a reasonable game without requiring
- all the players to become shipping clerks. The automated production
- and transfer parameters (see xxx) are almost always sufficient for
- a game. Explicit action should be limited to games where material
- limitations are so severe that they impact strategy directly,
- and players have to make hard choices between producing materials
- and doing other actions, on a turn-by-turn basis.
-
- You can define ``stevedore'' units by setting both rate and acp such that
- the u1 -> stevedore -> u2 transfer is faster and cheaper
- than the basic u1 -> u2 rate.
- Then players can use the stevedores to speed up transfers.
-
- @section Terrain Manipulation
-
- In a few games, you will want to let players alter the terrain.
- This needs to be done judiciously,
- since a cell of terrain generally represents a vast area,
- and the simulated time in @i{Xconq} is generally too short
- for major terraforming operations.
- However, building bridges and digging moats can be reasonable
- additions to a game.
-
- Since actions are always completed quickly,
- and there is no concept of ``partly modified terrain'',
- you will probably have to come up with a trick to make terrain modification
- be slow. One way is make the acp (or material?) cost very high.
- Another way is to make the alteration happen by removing a material,
- such as clearcutting a forest.
-
- @section Vision
-
- Vision is an important part of @i{Xconq}.
- Information need not come for free in your game design,
- and you can design the parameters to control how much players can get.
- The possibilities range from total knowledge as in board games,
- where nothing is secret except the enemy's heart,
- to games where much of the play hinges on who knows what, and when.
-
- @subsection Seeing All
-
- The simplest thing to do is to set @code{see-all} to @code{true}.
- Then every player sees all the terrain, everybody's units, everybody's
- occupants, the whole world and everything in it.
- This makes @i{Xconq} like a conventional video or board game,
- which is sometimes just what you want.
- Also, since the view matches the world, the game is simpler for players,
- who need not concern themselves with possibly out-of-date information.
- Finally, @code{see-all} is more efficient in time and space,
- since the general visibility calculations need never be done or recorded.
- Many games include @code{see-all} as one of their variants.
-
- You may also find @code{see-all} to be a useful game debugging aid,
- since you can watch what is happening everywhere in the world.
- Just remember that any AIs will most likely employ a different
- strategy, and that you won't be able to debug the other viewing
- parameters!
-
- @subsection Coverage
-
- Still, much of the fun in @i{Xconq} is the potential for surprise.
- The theory of visibility in @i{Xconq} is that each side has one or
- two layers of coverage, one for generic vision and one for specialized
- sensors, each of which basically just counts the eyeballs looking at
- each cell. As your units move around, the coverage in each cell
- goes up and down.
- Any cell with a coverage of zero is not currently being viewed
- by any of the player's units.
-
- The unit property @code{see-always} is useful for units like towns,
- which are unlikely to disappear secretly.
-
- These two parameters apply recursively, so for instance a city could be
- @code{see-always} and @code{see-occupants},
- while a building in the city is @code{see-always} and not
- @code{see-occupants}, with the net effect that units
- inside a city can be seen by everybody,
- but not when they enter a building.
-
- @code{already-seen} should usually be true of things like cities,
- independently of their @code{see-always} setting.
-
- @subsection Initial View
-
- The initial view represents the knowledge assumed to have been
- gathered over the period of time preceding the game.
- @i{Xconq} lets you set a radius around each initial unit,
- within which the side knows everything.
- Also, any people on your side view both their cell and all
- the adjacent cells.
-
- @subsection Vision Range
-
- The default vision range is 1, which basically means that units
- can see into adjacent cells but no further. Ranges > 1 make sense
- for tactical- and person-level games (especially when combined
- with LOS rules if they ever get implemented).
-
- You can also set the vision range of a unit to 0, which means that
- it can only see things in its own cell. However, as a special
- case, when such a unit enters a new cell, @i{Xconq} will show the
- terrain of each adjacent cell, but not any units that might be
- present. This is so players
- can decide which way to move without having to plunge blindly into
- unknown terrain or do some sort of awkward ``adjacent cell examination''
- action before moving.
-
- @section Backdrop Weather
-
- [The four temperature extremes are independent of each other,
- so you can make higher latitude temperatures vary drastically with the
- season, while equatorial temperatures are much more stable; or vice versa.
-
- Average temperature usually varies more slowly over some kinds of terrain
- than others. For instance, oceanic circulation moderates temperature
- swings in terrain that is near open ocean.]
-
- @section Backdrop Economy
-
- Economy in @i{Xconq} means pushing materials around. So if you want an
- economy in your game design, you have to define at least one type of
- material. To define the economy, you have to decide where materials
- come from, how they get moved around, and how they get used up.
-
- @subsection Creating Materials
-
- Materials come into existence either by placed in units or terrain
- during setup, by being produced by units or terrain, and by appearing
- in newly-created units.
-
- @subsection Moving Materials
-
- Once in existence, players can move materials around by explicit action.
- You can also define automated material movement that uses supply and demand.
- The tables @code{in-length} and @code{out-length} control the distance
- over which materials will move each turn.
-
- @subsection Consuming Materials
-
- Materials exist to be consumed (unless they are relevant to a scorekeeper).
- You can set how much each kind of action uses, as well as how much is needed
- as a prerequisite, sort of like a catalyst. You can also set consumption
- due to existence alone, plus what happens to a unit when it supply of a
- material runs out.
-
- [note role of money as a special material type]
-
- @section Random Events
-
- What simulation game would be complete without random events?
- Random events are handled somewhat similarly to synthesis methods,
- in that you set the value of the variable @code{random-events}
- to a list of the methods that you want run.
-
- Superficially, random events just introduce some unpredictability
- into a game. However, adding it just for its own sake is not
- a good idea; in the worst case, the game becomes the infamous
- ``dice-rolling contest'', where nothing matters except luck.
- Random events are more valuable when they introduce risk,
- and players have to balance that risk against their goals.
- As an example, random losses of cities in the standard game
- would be pointless, since players have to have them, and there
- would be a chance that all of a player's cities would disappear,
- causing the player to lose for no good reason at all.
- On the other hand, the chance of losing an expensive capital
- ship in shallow coastal waters is enough to motivate the player
- to keep them well out to sea.
-
- @subsection Accidents
-
- Accidents should be restricted to definite hazardous situations, to go along
- with movement constraints - for instance, carriers and battleships
- in shallow water should have a small chance to hit a rock and sink.
-
- You can specify two kinds of accident; a damaging accident,
- which hits the unit as if it were in combat, or a vanishing
- accident, in which the unit disapppears instantly.
-
- @subsection Attrition
-
- Attrition is a sort of higher-probability/lower-damage type
- of accident. It is useful for armies in hostile terrain,
- where deserters and casualties slowly reduce its strength.
-
- Attrition can be useful for ``aging''
- a unit, if you need to keep the unit from being around too long.
-
- @subsection Revolts
-
- Revolts are spontaneous changes of side, independent of any
- other consideration. Since there is no way to protect against
- this, the chance should usually be very small, less than .01;
- even a small chance of will cause players to maintain reserves
- just in case.
-
- @subsection Surrenders
-
- @section Designing the Interface
-
- So far, the game design machinery has been focused on semantics.
- The other part of the game design defines how it actually appears
- to the players. This part of the design can be more loosely
- designed, which is good, because you cannot guarantee that your
- game design will only ever be run with a particular interface,
- and there is a wide variety of interfaces. You could, for instance,
- define an elaborate set of color graphical icons and patterns,
- only to find that most of your players only have black-and-white
- displays. @i{Xconq} itself will always be able to cope with
- your omissions, but it will be forced to synthesize
- inferior substitutes.
-
- Game designs have three general categories of interface elements
- that they can specify: text, graphics, and animations.
- Text elements are just strings describing objects and events
- in a readable, while the graphics consists of small icons
- and patterns primarily representing units and terrain.
- Animations are used to illustrate events as they happen,
- and may include sounds.
-
- @section Designing Text
-
- Although @i{Xconq} is primarily a graphical game system,
- it is complex enough that the graphics alone are
- insufficient to describe what is going on.
-
- All text that players see is issued by @dfn{text generators},
- which are objects that, when given appropriate inputs,
- produce text fragments that can be used by the interface
- to produce a textual display.
- Each text generator has a number of parameters that
- may be used to select one of several rules [etc]
-
- @subsection Describing Objects
-
- [units, sides, etc]
-
- [should be able to have multiple descriptions for each type of object]
-
- @subsection Describing Events
-
- [should be able to have multiple descriptions for each type of event]
-
- @section Designing the Graphics
-
- @i{Xconq} is fundamentally a graphical game;
- fortunately, you don't have to do gnarly
- graphics hacking to get the pretty pictures!
- The basic graphics handling is built into the interface
- subroutines of @i{Xconq}.
- What you @i{do} have to do is to choose or design the basic images.
-
- @i{Xconq} will always attempt to generate
- some sort of default display for your new game design, but it's
- likely to be pretty ugly. So your goal here is just to make the
- display look good. First off you should decide about the overall
- appearance. Do you want things to be generally light or dark?
- Garish or subtle? Conventional or exotic? This is a good time
- to cruise the image libraries and to look at the graphics of other
- games. Sometimes the theme decides a lot for you - how could you
- display anything than a red star on a Soviet tank? You also need
- to think about whether you want to concentrate on b/w or color displays,
- although again @i{Xconq} will try to do something reasonable for both.
-
- You have to choose three sets of images: terrain patterns or images,
- unit icons, and side emblems. The terrain patterns have to tile properly,
- since they may be used to fill in large areas, while both unit icons
- and side emblems are single icons. You can optionally choose solid
- colors for terrain, and to ``colorize'' unit icons and side emblems.
-
- Once you chosen and specified a set of images, you have to try them
- out in various combinations in real games. What you'll most likely
- discover is that they don't always mix like you imagined. That
- cool-looking emblem for a side disappears against the background of
- space, or two unit icons are nearly indistinguishable on the map.
- At this point, you have to start making some tough choices.
- Either substitute some different images, or design new ones of your
- own.
-
- Color choices are tricky. Again, the total effect can be quite different
- from what you imagined, plus you should be careful about the variety
- of displays that your game runs on, or you may be getting complaints
- about how your ``olive'' more closely resembles ``puke gray''!
-
- Here is an example of unit icons:
- @example
- (add (infantry town city) image-name ("soldiers" "town20" "city20"))
- @end example
- In general, icon names describe the appearance of the image, and so
- do not necessarily match up directly with type names. The @code{"soldiers"}
- icon, for instance, just shows a row of soldiers; in one game the icon
- can be used to infantry, in another, armies in general, and in another, the
- national guard. There is in fact an @code{"infantry"} image also,
- but it is the standard ``crossed bandoliers'' symbol favored by the
- US Army, and is really only sensible for games involving US Army infantry.
-
- [example of terrain patterns and colors]
-
- For extra fine control on color displays,
- you can also set the colors of unseen terrain
- and the grid separating cells, via the globals @code{grid-color}
- and @code{unseen-color}.
-
- Note that some display systems (such as the X Window System)
- allow users to customize
- most or all of their colors, so individuals may override your choices.
- Not much you can do about that though!
-
- @subsection Image Format
-
- [describe when fleshed out]
-
- @subsection Image Design Hints
-
- The design of each graphical image can and should be somewhat independent
- of the basic game design;
- this allows for reuse of pictures.
-
- The first thing you should do is to check the image library on your
- machine. The image you're looking may already be there, but perhaps
- under a different name. Even if you don't find it, you may notice
- an image that is close enough to be a good starting point.
- The @i{Xconq} image library presently includes hundreds of images,
- so the chances are pretty good that you'll find something useful.
-
- Designing good images and patterns is a specialized and demanding category
- of artwork that I'm not going to go into here.
- My best advice is to learn from the pros,
- and don't be afraid to experiment.
-
- @section Game Module Organization
-
- Each separate file is known as a @dfn{game module} or just @dfn{module}.
- A module has a name, displayed name, an advertising-style blurb, a version,
- and designer notes.
-
- This is an example of an elaborately-declared game module with no
- actual content:
- @example
- (game-module "foobar"
- (title "Foo of Bar")
- (blurb "An exciting game with lots of cliffhanging suspense")
- (version "1.3")
- (program-version (>= "7.0.3"))
- ;; other properties?
- (complete-game true)
- )
-
- ;;; contents here
-
- (game-module (notes (
- "This is just a sample game."
- ""
- "It's not really as interesting as the blurb makes out."
- )))
-
- (game-module (design-notes (
- "This is commentary addressed to other designers."
- "Also a good place to mention things to work on."
- )))
- @end example
- The @code{notes} and @code{design-notes} could have been supplied with the
- first @code{game-module} declaration, but in practice, putting the
- player and designer notes at the end of the file
- keeps them out of the way.
- You can supply any number of @code{game-module} declarations in a file.
- Only the first need include a name.
-
- The game module format is only loosely structured.
- In general, anything that you might want to reuse or combine
- in different ways should be a separate module.
- Good candidates include text generators and maps of real terrain.
- Unfortunately, they don't always mix-and-match as well as you
- might like!
-
- @section General Techniques
-
- There are at least three ways to make a new game design:
- use @i{Xconq} commands to ``play'' a game and then save it,
- create and text-edit the text files defining a game,
- or write and run special-purpose programs
- that create games. A combination of these techniques will likely prove
- the most useful, since each alone has both strengths and weaknesses.
- For instance, text editing may seem like a crude approach,
- but is the only way to produce certain types of scenarios,
- and text editors have many facilities
- (such as regular expression replacement)
- not directly available in @i{Xconq}.
- On the other hand, maintenance of the correct
- transport/occupant relationships between units
- is hard to do while editing text,
- but comes for free when using @i{Xconq} itself.
-
- @node Building Scenarios, Language, General Techniques, Game Design
-
- @section Building Scenarios
-
- The easiest way to customize @i{Xconq} is to build a scenario.
- A scenario is basically a saved game from which irrelevant details,
- such as the list of players, has been omitted. Typically
- this will include tweaking details, removing random irrelevant junk,
- and generally tuning things.
-
- One way to do this would just be to start a normal game, save it, and
- then dig through the saved game and edit it, since the saved game is itself
- a game module. Sometimes this is easy, more likely it will be quite hard
- and error-prone. A better way is available, in the form of ``designer mode''.
-
- @subsection Designer Mode
-
- There are two way to get into designer mode; one is to start up a game
- with the appropriate option (@code{-B} under Unix), which makes
- every player with a display a designer, the other is to
- switch on a flag after the game has started.
- Being a designer is a property of a side,
- so in theory a game could have a designer and several other human players,
- or even multiple designers (this might be useful in having assistants to
- help with the construction of large scenarios, or just to have displays
- open to each side's view of the scenario). AIs effectively sit out the
- game while designers are present.
-
- Designer mode enables an additional set of commands on the menu or map
- control panel, as well as removing some restrictions on the use of
- normal commands. It also enables more elaborate game saving machinery,
- so you can save only the parts of a game that you want to make into a scenario.
-
- Modifications to normal commands include the permission to look at and
- do any command on any unit, including independents and units belonging
- to other sides.
- For instance, any unit can be renamed at any time by any designer in the game.
- The modications include the following:
-
- @itemize @bullet
- @item
- Move commands can put any unit at any destination instantly.
-
- @item
- Any unit can be put on any side.
-
- @item
- Any unit can be disbanded instantly.
-
- @item
- Any terrain can changed to any type.
- @end itemize
-
- Some interfaces may also provide additional tool palettes and the like.
-
- @subsection Saving Scenarios
-
- If you're not in designer mode, then saving the game will save absolutely
- everything.
- In designer mode, the interface should ask you what parts of the game you
- want to save, and what to name the module.
-
- If you don't save everything, then you should start up another game
- just to confirm that you got what you wanted, @i{before} shutting down the
- @i{Xconq} that you're designing with.
- Sometimes you won't have saved what you thought you did...
- It's also a good idea to keep a backup copy of data,
- especially the indecipherable area layers;
- use the nesting comments @code{ #| |# } around the old stuff,
- only delete when you're sure it's no longer of interest.
-
- @section Preparing a Game for Use
-
- Once you've constructed a game, you should bring it to a state where it
- can be given to other @i{Xconq} players. The process is like that for
- any other sort of software.
- Fortunately, @i{Xconq} game designs are usually smaller
- than C programs, so the usual software release problems
- are minimal. A version number is recommended, preferably
- a distinct number for each time you change it.
-
- @subsection Installing Scenarios
-
- Once the scenario is constructed and saved, you can install it in the library
- and otherwise do as you like with it.
- See the specific interface documents for installation details.
-
- @subsection Safety
-
- While generally safe -- @i{Xconq} shouldn't crash while you are designing
- nor upon starting up your scenario -- you can do silly things,
- like loading a submarine with battleships as passengers.
- @i{Xconq} won't complain, but it may behave very strangely.
- For instance, a unit might be able to travel with a transport and leave it,
- but not be able to get back on again.
-
- One way to test a game is to remove all the scorekeepers and
- make all the players be AI-controlled. The AI code will then
- act totally randomly and thus exercise parts of your design
- that you may not have thought about.
-
- @subsection Balance and Playtesting
-
- More importantly, scenario design can involve
- subtle questions of balance, which
- can only revealed by repeated play of the scenario. Playtesting is
- extremely important, even for simple scenarios! You should try as many
- combinations of startup options as possible - for instance, the combo
- of two humans and one machine might reveal a peculiarity that is not
- observed in a two-person game.
- You can solve many problems by adding more restrictions.
- Since the scenario is your concept, you are free to make whatever
- decisions are necessary to realize that concept; if somebody
- complains, they are free to make their own designs.
-
- Playtesting is also the time when you may have to sacrifice realism
- and favorite theories for playability. Listen to and watch yourself and your
- testers as the game is played. For instance, you might have included a city
- out in the boonies, but in the game it never does anybody much good, while
- still requiring some amount of attention regularly. Lose it.
-
- Game startup can be confusing to players if they all start out with
- lots of units needing to be told what to do.
- One solution is to put most unit on automatic behaviors that expire
- in a turn or two, so that novices gradually hear from all the units,
- while experts can still override right from the outset.
- Another approach is to make units independent and allow them to be
- captured early on.
- Still another approach is to make units come in as reinforcements
- at preset times and locations.
-
- Although as many of the game parameters as possible are checked,
- there is plenty of room for subtle loopholes. You should think carefully
- about the consequences of each parameter, being particularly sensitive to
- degenerate winning strategies. Most common are units that are too powerful,
- too fast,
- or are built so quickly that they overwhelm any opposition.
- Players should always be a little ``hungry'';
- not able to get quite as many
- units or as much material as they would really like.
-
- @subsection Complexity
-
- Although GDL is a powerful language,
- you should avoid designing a game that is too complex to be humanly playable.
- A single game can literally define
- millions of different numbers, each with a range including 100 to 10,000
- distinct values. It is clearly possible to spend many
- years exploring just a single set of these numbers. For more playable and
- enjoyable games, either pick a single things to treat in detail, or else
- do everything in a simplified way.
- For instance, if you want elaborate movement and combat rules,
- avoid or even eliminate materials and associated material handling rules.
- Another thing to
- keep in mind is that the introduction of a new type may have far-reaching
- consequences - a new unit type will need its interactions with @i{all}
- other unit types defined. One approach is to introduce a new type as a
- slight modification of an existing type, then to share most of the
- definitions.
- Another thing you can do is to put complexity into the variants,
- so players with a taste for punishment can indulge themselves
- without making everybody else suffer.
-
- @subsection Combinations
-
- Many of the 700-odd game parameters were
- chosen for their ability to combine in interesting ways,
- rather than for obvious usefulness.
- For instance, construction in a city can by default
- generate an infinite stream of units.
- But suppose you want to put a limit on the numbers of that type of unit?
- One way is to define a material that
- is essential for construction of that type, let the builder have an initial
- supply, but provide no way to get more of that material. When it runs out,
- no more units!
-
- Another trick is to motivate an activity by making it a
- prerequisite to the basic builtin goal of defeating the other player.
- The age of discovery worked this way. The kings of that time weren't
- interested in new lands per se; they wanted exploitable possessions that
- could be used to get gold to buy armies big enough to defeat their neighbors.
- You could describe this situation almost exactly, by making
- gold a material, obtainable only by the discovery and capture of independent
- gold mine units, which are thinly scattered over the world
- and can be found only by careful exploration.
-
- Be inventive!
- Studying the predefined games should suggest many tricks;
- the ``Problems and Solutions'' section below describes
- even more.
- Be sure to document the trick carefully, or the next time you
- work on the game, you might break it and will have unhappy
- players wondering why their usual strategies don't work anymore.
-
- @node Debugging, Examples, Combining Parameters, Design Hints
-
- @section Debugging
-
- Completely new game designs usually have a number of bugs.
- There are several stages of trouble that you may encounter.
- First, the @i{Xconq} may fail to read a game module completely.
- It will try to report what happened, but if for instance you
- left out a closing parenthesis, you may get some strange error
- messages. This is just plain old syntax error trouble.
-
- Once you've successfuly read in your new game,
- bring up the online help and scan through to see if the values
- present are what you thought.
- Sometimes the reader does not interpret a module in the way
- you thought it would.
- The @code{print} form is useful for debugging at this point;
- it can show you whether a defined symbol has the value you
- thought it did.
-
- However, the most serious
- problems with games are play balance issues. Some can be found out by
- watching a machine player attached to a display,
- since its decisions are based on perceived values of the units.
- The most subtle bugs can only be uncovered by extensive play
- interspersed with judicious alteration of parameters.
- I find it useful to play for a while,
- then review and adjust the game parameters all at once,
- thus avoiding tweaking one parameter only to find that it results in
- another being inconsistent.
- Parameters interact in many ways - you should keep this in
- mind when experimenting.
-
- Something else to keep in mind at this point is that playability should
- outweigh realism. For example, real-life airplanes can travel 1,000
- times faster than a person walking on the ground, but airplanes that
- could move 1,000 cells in a turn would be ridiculous
- (try it out, @i{Xconq} WILL let you do this!).
-
- @section Problems and Solutions
-
- This section discusses specific kinds of design problems and ways that
- you might solve them in @i{Xconq}. These are merely suggestions;
- in the past, game designers have come up all sorts of ingenious ideas.
- If you come up with one yourself, please pass it along!
-
- @subsection Limiting Unit Quantities
-
- In some cases you may want to constrain the total number of units in play,
- perhaps because of performance reasons, or because some type tends to
- proliferate more than is desirable, or because your game concept requires
- a hard limit on the number of units. You have several ways to do this.
-
- @i{Xconq} does give you several parameters
- that put a simple cap on total numbers, either by unit type or for all
- units, and per side or for all sides together.
- You can also define a material type that is essential to the creation,
- completion, or operation of units, and make that material be hard to come by.
- Iron to make ships, gold to pay armies, or food to feed armies could all
- work this way. If the only source of the limiting material is an initial
- supply in a starting unit, then this is a hard limit; if production of the
- limiting material is slow, then the limit is softer but still very real.
-
- Limits on unit quantities have some interesting uses beyond the obvious ones.
- For instance, a
- useful type that is limited to at most a single instance could be a sort of
- ``football'' where the side that has the one unit finds itself being
- chased after by all the other sides trying to get it.
- You could make a WWII-era game with
- ``Oppenheimer'' as the only scientist who knows how to make
- an atomic bomb (I know, it's not realistic), and have the different sides
- trying to kidnap him.
-
- @subsection Handicapping
-
- Very rarely will the @i{Xconq} players in a game all be at the same skill
- level. Sometimes this is OK, since weaker players really do learn more
- from their losses than their wins. However, when the goal is to have fun,
- or when the difference in abilities is extreme, you can balance things out
- in several different ways.
-
- One simple approach is just to design an imbalanced scenario, document
- it as such, and let players choose the stronger and weaker sides as desired.
- In many cases this should be sufficient; for instance, accurate historical
- simulations.
-
- The next most simple solution is to set up sides or side classes and
- fill random properties differently. Weaker players could choose a side with
- more technology or whose class allows more powerful units. This isn't
- very adjustable, since all the sides and their property values
- have to be predefined.
-
- To enable the most precise match of player abilities, you can use the
- @code{initial-advantage} property of player objects. This property is
- a relative value, defaulting to 1, and indicates how strong the initial
- unit setup should be relative to the other players. For instance,
- if a three-player game includes advantages of 2/3/7, then the second player
- will have three units for each two of the first player while the third
- player (the weakest) will have seven. The implementation of relative
- advantages is up to game synthesis, so for example the @code{make-countries}
- will adjust all the numbers of initial units to match the requested
- advantages. Note that this affects only the initial setup, and only
- certain synthesis methods.
- Once a game has started, all sides are always on an equal footing.
-
- @subsection Buying the Initial Setup
-
- A common form of game setup is to give each player a quantity of ``money''
- of some sort, then give them a menu from which to buy things. The way you
- would implement this in @i{Xconq} is similar to the method for limiting
- unit quantities - make the money be an initial supply of a special material
- type not used for any other purpose. This initial supply should be given
- to a first unit that each player starts with. This first unit could be
- something like the adventurer in a fantasy game who starts with a pot of money,
- so the first unit is also the most important one,
- or perhaps a little dummy unit that
- buys the other units and then is of little interest thereafter, sort of like
- the national bank for the player's country.
-
- Here's an example:
- @example
- (unit-type adventurer
- (start-with 1)
- )
- (unit-type shop
- (start-with 1)
- )
-
- (unit-type sword)
- (unit-type armor)
- (unit-type boat)
-
- (material-type money)
-
- (table initial-supply (adventurer money 200))
-
- (table acp-to-create (shop (sword armor boat) 1))
-
- (table material-to-create ((sword armor boat) money (20 100 1000)))
- @end example
- The shop can't do anything besides create items when given money.
- The adventurer starts with the money and has to give it to his/her shop,
- then order the shop to create the
- items desired. The shop will create completed items instantly,
- ready for the adventurer to use.
-
- Note that this can't be extended to buy extra intrinsic qualities,
- such as hit points or action points.
-
- @subsection Leaders
-
- Some games, particularly wargames set in Napoleonic times or earlier,
- feature the concept of a ``leader'' as the sole individual who can make
- things happen. Without a general or field marshal, the army won't move.
-
- One way to do this is to make the leader be a self-unit and limit the
- distance of direct control over other unit types.
-
- Another way is give armies 0 acp and allow leaders to push them around.
-
- Another way is to use leaders as occupants that add to armies' mp.
-
- @subsection Navigable Rivers
-
- The concept of a navigable unbridged river is a real problem for @i{Xconq}.
- Non-navigable rivers are easily done as border terrain,
- and navigable rivers with lots of bridges can be connections
- (since by their nature, connections can never prevent movement).
- But a navigable river that can't be crossed easily is more of a problem.
- One way is to make a chain of adjacent cells of a water terrain type.
- However, this can be quite unrealistic if cells represent large areas,
- say 10-100 km across; you can end up with continents consisting of more
- river than land. In some cases, you can define a ``river valley''
- terrain type where both vessels and ground units can exist, with the
- river border terrain along just one edge of the valley.
-
- You can also allow border sliding. Border sliding allows a ship to pass
- along the length of a border, but it does require the ship to be in
- compatible terrain at both ends of the border. So define the river
- as a chain of alternating water cells and water borders connecting them
- together. Then the river acts as a barrier to units wanting to cross,
- while allowing them to see over to the other side,
- and at the same time ships can pass up and down the river freely
- (modulo any ZOC exerted by units on either side).
-
- @subsection What Ranges for Values?
-
- One of the problems that you encounter when defining a lot of interrelated
- units with lots of properties and tables
- is to decide where to start out with the numbers.
- There are a couple ways to get started.
-
- First, you can start from real-world numbers. Let's say your game concept
- is based on turns that last about one day, and you want to use worlds
- with cells that are about 10 miles across. Now a person in good shape
- can walk about 2 miles per hour, or 20 miles in a day, which comes out
- to 2 cells/turn as @code{acp-per-turn} for units on foot. This allows
- a speed of 1 cell/turn for injured, tired, or overburdened persons, via
- the various speed modifiers. However, if this same game includes
- automobiles and airplanes, then using the same calculation,
- we get automobiles that can move 60 cells/turn and airplanes that can
- move 600 cells/turn! The massive disparity in speeds makes for poor
- playing; every turn each airplane will make 300 moves while the foot
- traveller makes 1. To make the game work, you'd have to make airplanes
- slower (they have to refuel a lot perhaps) or make people faster (nobody
- walks anywhere anymore). So the real-world numbers approach isn't
- foolproof.
-
- Another way to go is to start with the smallest values and work up.
- For instance, in the monster game above, you could assume that the mob moves
- the slowest, and give it a speed of 1. Then you say that the national
- guard should be able to move twice as fast, and give it a speed of 2.
- Then the monster should be able to chase and catch mobs and guards
- that run away, so you give it a speed of 3 or more. This approach
- is more painstaking, particularly when lots of numbers are involved.
-
- You can use both approaches together as well, working with real-world
- numbers until they get too weird, then adjust to make relative values
- sensible, then do some more real-world calculations.
- As always, only playtesting is the final arbiter.
- Once the numbers ``feel'' right in a game,
- only the obsessive-compulsives will care about their exact values.
-
- @subsection Fatigue
-
- Players are often unmerciful to their units, moving them nonstop,
- going into battle after battle, never a thought for how tired the
- poor units might be.
- Although @i{Xconq} does not include fatigue as a basic concept, it does
- have several ways to implement the effects of fatigue.
-
- One way is to use acp debt. If you allow the acp to go negative during a turn,
- then the player can work the unit really hard for one turn, then it has to
- rest until its acp builds up to positive levels again. While acp is negative,
- the unit can take no action on its own. Over a period of
- time, the effect is that of a unit that can only do so much,
- but can exert itself when needed.
-
- Another way to do fatigue is via a material type, perhaps called
- ``energy'' or ``enthusiasm''. As an abstract sort of material,
- don't let energy be passed around (unless you want to have ``infectious
- enthusiasm'', might be useful sometimes for leaders and morale builders).
- Units need energy in order to move, and can consume energy faster
- than they produce. For instance, if a unit has a speed of 3 hexes/turn,
- consumes 2 units of energy per move, and only produces 4 units of energy
- each turn, then on the average the unit will only be able to move 2 hexes
- in each turn, although if it saves up energy, then it can move the full
- 3 hexes.
- Since different kinds of terrain can have differing productivity,
- you can also make some kinds of terrain be more tiring than others.
- A resort hotel unit could also be allowed to transfer energy to its
- residents, restoring them faster than a Motel 6.
-
- @subsection Brainless Units and Scorekeeping
-
- One special case to watch out for occurs in games with ``unintelligent''
- units, that is, they have an acp of 0. If a side loses all of its units
- except for the unintelligent ones, the player will not be able to do
- anything except wait for the game to end.
- This might be OK, for instance if the idea of the game allows
- for a side to own a particular unit, whether or not it can do anything
- with it (perhaps the unit is a fort, and a side can win if it owns the
- fort, even at the cost of all its other units). Usually, however, the
- side ought to just lose, in which case you will need to define a special
- scorekeeper that requires each side to have at least one of some
- sort of unit with acp > 0, or else it loses.
-
- @subsection Days and Years
-
- [should go elsewhere]
-
- The @i{Xconq} world can be made to revolve around its sun and to rotate
- on its axis. [etc]
-
- To get a realistic hour-by-hour simulation, say
- @example
- (world
- (day-length 24)
- (year-length 8766) ; this is 365.25 days
- )
- @end example
-
- @subsection Xconq 5.x SetProduct
-
- @i{Xconq} version 5 had a sometimes-useful flag called ``setproduct''
- that could be set to false, with the effect that any attempts to
- *change* construction were disabled. So for instance, a city that
- was set by a scenario to build bombers would then build bombers
- throughout the game. The advantages were both in realism (retooling
- a factory can be very time-consuming) and in playability (no construction
- planning required).
-
- To emulate this in version 7, you can set @code{acp-to-toolup}
- to be zero for cities, but at the same time require 1 tp for each
- type that the city can construct. In the scenario, set the value
- of the city's tooling to be 1 for the one or more types that you
- want it to specialize in (maybe switching between fighters and
- bombers should be possible, but not to submarines).
- Players can then start and stop construction as desired,
- but are limited to only particular types.
- Even captured independent cities can be limited in what they
- can be used to construct.
-
- @section Optimization
-
- The @code{add} form is very powerful and very useful for making
- groups of objects share some data. The grouping also helps the
- designer to see how sets of numbers compare to each other.
- In other words, instead of having multiple forms:
- @example
- (unit-type foo
- ...
- (acp-per-turn 3)
- ...)
- (unit-type bar
- ...
- (acp-per-turn 49)
- ...)
- (unit-type baz
- ...
- (acp-per-turn 2)
- ...)
- @end example
- you can say
- @example
- (add (foo bar baz) acp-per-turn (3 49 2))
- @end example
- to get the same effect.
-
- To get an inheritance-like effect, you can append lists of types
- together, as in
- @example
- (define mammal (dog cat cow))
- (define bird (hawk eagle condor))
- (define animal (append mammal bird fishie))
- @end example
- which results in a list of seven types. It is possible to append
- different kinds of objects together.
-
- @subsection Preferred Module Names
-
- Terrain-only modules should be @code{t-xxx}.
-
- Lists of units should be @code{u-xxx}.
-
- Name generators should be @code{ng-xxx}.
-
- @section Junk to Describe Better
-
- An unwanted unit in a shared lib file
- could be gotten rid of by matching on id or
- name and then setting hp to 0 - (unit "Corinth" (hp 0)) for instance.
-
- [this doesn't actually work]
- Elevation data, while interesting to include, can take up a lot of space
- and be more detailed than necessary. The parameters here allow you to
- restrict elevations to a smaller range of values, which will allow
- for more compact encoding and simpler games.
- For instance, a game set in rolling countryside doesn't need a huge
- range of elevations; you could set elevations to range from 0 to 300
- meters, in 30-meter increments. Then only 4 bits will be needed to
- encode each value, and yet the player will still see reasonable values
- like "150 meters", and formulas for temperature and other elevation
- dependent data will be correct.
-
- Note that just because a player controls a side doesn't mean that the
- controlled side can be taken out of the game; for one thing, certain
- types of units will not change sides under any circumstances.
-
- People materials should usually not be directly movable
- between units.
-
- ZOC should be < combat range usually, means that exerter should be able to
- control ground (but could attack further in multiple turns).
- ZOC levels only those reachable by the unit.
-
- With all the costs of moving around,
- it may be that a unit has movement points left, but
- not enough to meet the full cost of a desired move action.
- You can allow player extra movement points to complete the action
- by setting @code{free-mp} to effectively add the needed mp.
-
- A hit on a complete unit should reduce by whole cp/hp, otherwise
- will appear to be incomplete. @i{Xconq} will not fix this,
- you have to arrange all the numbers yourself, or run the risk
- of player confusion.
-
- You can define wind-affected units by defining speed in each direction
- (max-speed only, do others proportionally). Would need 4 distinct mp costs
- plus a formula to relate to wind strength. Wind speed defined as "how
- far a particle of air moves in a turn". Unit examples include balloons,
- sailing ships, floating cities.
-